package com.eco.fishway.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 */
@Data
@Component
@Slf4j
public class KndInNettyClient {

    @Value("${knd.in.host:}")
    private String host;

    @Value("${knd.in.port:}")
    private Integer port;

    @Value("${knd.in.server-id:}")
    private String serverId;

    private Bootstrap kndBootstrap;
    private final NioEventLoopGroup kndEventLoopGroup = new NioEventLoopGroup();


    @PostConstruct
    public void runInKnd() {
        this.kndBootstrap = new Bootstrap();
        this.kndBootstrap.group(this.kndEventLoopGroup).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_KEEPALIVE, true).handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                KndInNettyClient.log.info("正在连接进口knd-tcp中...");
                ChannelPipeline pipeline = ch.pipeline();
                pipeline.addLast(new KndEncoder());
                pipeline.addLast(new KndDecoder());
                pipeline.addLast(new IdleStateHandler(0L, 1L, 0L, TimeUnit.HOURS));
                pipeline.addLast(new KndInHexHandler());
            }
        });
        kndReconnect();
    }



    public void kndReconnect() {
        this.kndBootstrap.remoteAddress(host, port);
        ChannelFuture channelFuture = this.kndBootstrap.connect();
        channelFuture.addListener((GenericFutureListener<? extends Future<? super Void>>) future -> {
            if (future.cause() != null) {
                log.error(host + ":" + port + " connect failure,retry...");
                ((ChannelFuture)future).channel().eventLoop().schedule(() -> {
                    kndReconnect();
                }, 3L, TimeUnit.SECONDS);
            } else {
                log.info(host + ":" + port + " connect success!");
            }
        });
    }

    @PreDestroy
    public void shutdown() {
        this.kndEventLoopGroup.shutdownGracefully();
        log.info("关闭knd连接");
    }
}